package org.ky.generator.component;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.apache.commons.lang.StringUtils;
import org.ky.generator.base.DefaultGenerator;
import org.ky.generator.config.DatabaseTableConfig;
import org.ky.generator.config.GeneratorCofig;
import org.ky.generator.config.PackageConfig;
import org.ky.generator.util.AttributeHelper;
import org.ky.generator.util.JdbcHelper;

import com.raddle.jdbc.callback.ConnectionCallback;
import com.raddle.jdbc.meta.table.ColumnInfo;
import com.raddle.jdbc.meta.table.TableInfo;
import com.raddle.jdbc.meta.table.TableMetaHelper;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;

/**
 * MyBatisSqlMap配置文件生成器
 * 
 * @author K.y
 * @since 2018-12-06
 *
 */
public class SqlMapGenerator extends DefaultGenerator {
	/** 输出文件路径 */
	protected static final String OUTPUT_FILE_BASE = "target/ibatis/base";
	/** 输出文件路径 （拓展） */
	protected static final String OUTPUT_FILE_EXTEND = "target/ibatis/extend";
	/** 基础SqlMap模版 */
	protected static final String TPL_BASE_SQL_MAP = "template/ibatis/baseSqlMap.ftl";
	/** 完全SqlMap模版 */
	protected static final String TPL_SQL_MAP = "template/ibatis/sqlMap.ftl";
	/** 默认动作 */
	protected static final String DEFUALT_ACTION = "game/value-added-step";

	public static SqlMapGenerator sqlMapGenerator = new SqlMapGenerator();

	private SqlMapGenerator() {
	}

	public static SqlMapGenerator getInstance() {
		if (sqlMapGenerator == null)
			sqlMapGenerator = new SqlMapGenerator();
		return sqlMapGenerator;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void generator() {
		logger.debug("开始生成MyBatis的SqlMap配置文件");
		try {
			new File(OUTPUT_FILE_BASE).mkdirs();
			FileUtils.cleanDirectory(new File(OUTPUT_FILE_BASE));
			new File(OUTPUT_FILE_EXTEND).mkdirs();
			FileUtils.cleanDirectory(new File(OUTPUT_FILE_EXTEND));
		} catch (IOException e) {
			logger.error("创建mybatis文件路径失败", e);
			e.printStackTrace();
		}
		List<TableInfo> tableInfoList = (List<TableInfo>) JdbcHelper.createJdbcTemplate()
				.execute(new ConnectionCallback() {
					public Object doInConnection(java.sql.Connection con) throws SQLException {
						TableMetaHelper metaHelper = new TableMetaHelper(con);
						return metaHelper.getTableInfo(DatabaseTableConfig.getGenTables(), new String[] { "TABLE" });
					}
				});

		for (TableInfo tableInfo : tableInfoList) {
			tableInfo.setTableName(tableInfo.getTableName());
			try {
				genOneTable(tableInfo, DEFUALT_ACTION);
			} catch (Exception e) {
				logger.error("生成表对象数据失败：[" + tableInfo.getTableName() + "]", e);
			}
		}
	}

	/**
	 * 生成单个表对应的SqlMap方案
	 * 
	 * @param tableInfo
	 * @param action
	 * @throws Exception
	 */
	public static void genOneTable(TableInfo tableInfo, String action) throws Exception {
		Map<Object, Object> root = new HashMap<Object, Object>();
		// 类属性和列名
		List<Map<Object, Object>> props = new ArrayList<Map<Object, Object>>();
		for (ColumnInfo columnInfo : tableInfo.getColumnInfos()) {
			Map<Object, Object> m = new HashMap<Object, Object>();
			if (columnInfo.isPrimaryKey()) {
				root.put("id", AttributeHelper.getPropertyName(columnInfo.getColumnName()));
				root.put("columnId", columnInfo.getColumnName());
			}
			m.put("name", AttributeHelper.getPropertyName(columnInfo.getColumnName()));
			m.put("propertyTypeName", AttributeHelper.getJavaType(columnInfo));
			m.put("columnName", columnInfo.getColumnName());
			m.put("columnTypeName", columnInfo.getColumnTypeName());
			props.add(m);
		}
		root.put("namespace", PackageConfig.getMapperPath() + "."
				+ AttributeHelper.getClassName(tableInfo.getTableName()) + "Mapper");
		root.put("properties", props);
		root.put("l", "{");
		root.put("r", "}");
		// 表名
		root.put("tableName", tableInfo.getTableName());
		root.put("className",
				PackageConfig.getModelPath() + "." + AttributeHelper.getClassName(tableInfo.getTableName()));
		root.put("simpleClassName", AttributeHelper.getClassName(tableInfo.getTableName()));
		root.put("beanName", StringUtils.uncapitalize(AttributeHelper.getClassName(tableInfo.getTableName())));
		root.put("criteria", PackageConfig.getCriteriaPath());
		// root.put("sort", sort);
		root.put("dollar", "$");
		root.put("nameUtils", new AttributeHelper());

		Configuration cfg = new Configuration();
		cfg.setClassForTemplateLoading(SqlMapGenerator.class, "/");
		cfg.setObjectWrapper(new DefaultObjectWrapper());
		cfg.setDefaultEncoding(GeneratorCofig.UTF8);
		Template baseTemp = cfg.getTemplate(TPL_BASE_SQL_MAP);
		Writer baseOut = new FileWriterWithEncoding(
				new File(OUTPUT_FILE_BASE, AttributeHelper.getClassName(tableInfo.getTableName())) + "Mapper.xml",
				GeneratorCofig.UTF8);
		baseTemp.process(root, baseOut);
		Template temp = cfg.getTemplate(TPL_SQL_MAP);
		Writer out = new FileWriterWithEncoding(
				new File(OUTPUT_FILE_EXTEND, AttributeHelper.getClassName(tableInfo.getTableName())) + "Mapper.xml",
				GeneratorCofig.UTF8);
		temp.process(root, out);
		out.close();
	}
}
